﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Text.RegularExpressions;

namespace RSSReader
{
    [XmlRoot("RSSFeeds", Namespace = "RSSFeeds", IsNullable = false)]
    public class RSSFeeds : IEnumerable<RSSFeed>
    {
        public List<RSSFeed> Feeds;

        public IEnumerator<RSSFeed> GetEnumerator()
        {
            return Feeds.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public RSSFeeds()
        {
            Feeds = new List<RSSFeed>();
        }

        public void Add(object feed)
        {
            Feeds.Add((RSSFeed)feed);
        }
    }

    public class RSSFeed
    {
        public string RSSName { get; set; }
        public string RSSUrl { get; set; }
        public DateTime LastUpdate { get; set; }

        public RSSFeed(string name, string url)
        {
            RSSName = name;
            RSSUrl = url;
            Init();
        }

        public RSSFeed()
        {
            Init();
        }

        private void Init()
        {
            LastUpdate = DateTime.Now.AddDays(-30);            
        }

        public RSSItems GetNewItems(RSSTitlesToMatch titlesToMatch, RSSItems allRssItems, RSSIgnoreList ignoreList)
        {
            List<string> log = new List<string>();

            RSSItems items = new RSSItems();
            //            XmlTextReader rssReader = new XmlTextReader("http://www.torec.net/rss.asp");
            //XmlTextReader rssReader = new XmlTextReader("http://tvrss.net/search/index.php?show_name=Desperate+Housewives&show_name_exact=true&mode=rss");           
            //XmlTextReader rssReader = new XmlTextReader(RSSUrl);

            HttpWebRequest httpRequest = (HttpWebRequest) WebRequest.Create(RSSUrl); 
            httpRequest.MaximumAutomaticRedirections=5;
            httpRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.50110;)"; 
            XmlDocument xmlDocument;

            try
            {
                XmlReader rssReader = XmlReader.Create(httpRequest.GetResponse().GetResponseStream());
                xmlDocument = new XmlDocument();
                xmlDocument.Load(rssReader);
            }
            catch (WebException)
            {
                return items;
            }
            catch (XmlException)
            {
                return items;
            }
            catch (IOException)
            {
                return items;
            }

            DateTime maxDate = LastUpdate;
            log.Add(DateTime.Now +  ": Checking RSS feeds on " + RSSName + " with date: " + maxDate);

            XmlNodeList list = xmlDocument.GetElementsByTagName("item");
            foreach (XmlNode node in list)
            {
                log.Add("Handling title " + node["title"].InnerText);

                string pubDate = node["pubDate"].InnerText;
                DateTime publicationDate = DateUtils.ParseRfc822Date(pubDate);
                publicationDate = publicationDate.ToUniversalTime();
                if (publicationDate > maxDate)
                {
                    log.Add("Setting new max date to " + publicationDate);
                    maxDate = publicationDate;
                }

                if (publicationDate <= LastUpdate)
                {
                    log.Add("Skipping title because pub time " + publicationDate + " is earlier than " + LastUpdate);
                    continue;
                }


                string title;
                //if (RSSUrl.ToLower().Contains("sratim.co.il"))
                //{
                //    string releaseName = "גרסת שחרור:";
                //    title = Regex.Match(node["description"].InnerText, releaseName + "(.+?)<").Groups[1].Value;
                //}
                //else
                    title = node["title"].InnerText;
                int pos = title.IndexOf("|");
                if (pos > -1)
                    title = title.Substring(pos + 1);

                title = Utils.CleanName(title);

                FindTitle(items, log, node["link"].InnerText, publicationDate, title, titlesToMatch, allRssItems, ignoreList, true);
            }

            LastUpdate = maxDate;
            
            log.Add(DateTime.Now +  ": Setting new last update to " + maxDate);
            
            StreamWriter sw = new StreamWriter("RssReaderLog.txt", true);
            foreach (string line in log)
                sw.WriteLine(line);
            sw.Close();

            return items;
        }

        public static void FindTitle(RSSItems items, List<string> log, string link, DateTime publicationDate,
                              string rssItemTitle, RSSTitlesToMatch titlesToMatch, RSSItems allRssItems, RSSIgnoreList ignoreList,
                              bool checkExistenceAndAge)
        {
            string dummy;
            log.Add("Searching for title matches of " + rssItemTitle);

            RSSTitleToMatch matchedTitle = null;
            for (int i = 0; i < titlesToMatch.Titles.Count; i++)
            {
                matchedTitle = titlesToMatch.Titles[i];
                string titleName = Utils.CleanName(matchedTitle.Title.ToLower());
                rssItemTitle = Utils.CleanName(rssItemTitle);
                if (!rssItemTitle.ToLower().Trim().Contains(titleName))
                {
                    continue;
                }

                bool shouldIgnore = false;
                foreach (string itemToIgnore in ignoreList.IgnoreList)
                {
                    if (rssItemTitle.ToLower().Trim().Contains(itemToIgnore.ToLower().Trim()))
                    {
                        shouldIgnore = true;
                        break;
                    }
                }
                if (shouldIgnore)
                {
                    log.Add("Ignoring " + rssItemTitle);
                    continue;
                }
                    
                RSSItem item;
                if (!matchedTitle.IsMovie)
                {
                    int titleEndPos = -1;
                    SeriesEpisode seriesEpisode = Utils.GetSeriesEpisodeUsingSXEPattern(rssItemTitle, out titleEndPos);
                    if (seriesEpisode == null)
                    {
                        seriesEpisode = Utils.GetSeriesEpisodeUsingSeasonEpisodePattern(rssItemTitle, out titleEndPos);
                    }
                    if (seriesEpisode == null)
                    {
                        seriesEpisode = Utils.GetSeriesEpisodeUsingSEPattern(rssItemTitle, out titleEndPos);
                    }

                    if (seriesEpisode != null)
                    {
                        rssItemTitle = rssItemTitle.Substring(0, titleEndPos);
                        rssItemTitle = Utils.CleanRssItemTitle(rssItemTitle);
                        item = new RSSItem(rssItemTitle, seriesEpisode.Season, seriesEpisode.Episode, publicationDate, link);
                    }
                    else
                    {
                        rssItemTitle = Utils.CleanRssItemTitle(rssItemTitle);
                        item = new RSSItem(rssItemTitle, publicationDate, link);
                    }
                }
                else
                {
                    rssItemTitle = Utils.CleanRssItemTitle(rssItemTitle);
                    item = new RSSItem(rssItemTitle, publicationDate, link);
                }

                if (checkExistenceAndAge &&
                    ( !ShouldAddItem(item, allRssItems) || !ShouldAddItem(item, items) ) )
                {
                    item.State = AddState.FoundAndAlreadyExists;
                }
                else
                {
                    string titleToMatch = link;
                    if (!link.ToLower().Contains("serethd") && !link.ToLower().Contains("torec.net") && !link.ToLower().Contains("sratim.co.il"))
                    {
                        titleToMatch = "\"" + rssItemTitle + (item.IsSeries ? String.Format(" S{0:00}E{1:00}", item.Season, item.Episode) : "") + "\"";
                    }

                    string qualityStr = Utils.GetQualityString(matchedTitle.Quality);
                    string saaPath = ConfigurationSettings.AppSettings.Get("RapidSearcher");
                    string command = saaPath + "RapidSearcher.exe";
                    string parameters  = titleToMatch + " false " + qualityStr;
                    log.Add("Running: " + command + " " + parameters);
                    int ret = Utils.RunShell(command, parameters, out dummy);
                    if (ret == 0)
                    {
                        log.Add("Adding succeeded: " +  dummy);
                        item.State = AddState.FoundAndAdded;
                    }
                    else
                    {
                        log.Add("Adding failed: " + dummy);
                        item.State = AddState.NotFound;
                    }
                }

                items.Add(item);
            }
        }

        private static bool ShouldAddItem(RSSItem item, RSSItems items)
        {
            if (item.Title.Equals("dvd", StringComparison.InvariantCultureIgnoreCase) ||
                item.Title.Equals("dvdrip", StringComparison.InvariantCultureIgnoreCase) ||
                item.Title.Equals("hdtv", StringComparison.InvariantCultureIgnoreCase))
                return false;

            foreach (RSSItem curItem in items.Items)
            {
                if (curItem.State == AddState.FoundAndAdded && curItem.Title.Equals(item.Title, StringComparison.OrdinalIgnoreCase))
                {
                    // Both movies with the same name
                    if (!curItem.IsSeries && !item.IsSeries)
                        return false;

                    if (curItem.IsSeries && item.IsSeries)
                    {
                        // Both series and current is season < curItem.Season
                        if (curItem.Season > item.Season)
                            return false;

                        if (curItem.Season == item.Season)
                        {
                            // Both series with the season and curItem.episode < item.episode
                            if (curItem.Episode >= item.Episode)
                                return false;
                        }
                    }
                }
            }

            return true;
        }



    }

}
